lemonoil


OI__nothing is impossible


感觉之前拿点分治水过心里过意不去,。。。。。mdzz,我还是打了一份树链剖分的code,具体方法与QTree4相同(详见代码),维护线段树的合并时的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define pf push_front
using namespace std;
const int N=1e5+1e2;
const int INF=0x3f3f3f3f;
struct node{
int l,r;
node(int l=0,int r=0):l(l),r(r){}
}seg[N<<2];
int n,dfs_cnt,cnt,cs,tot,Q,xx,yy;
int fa[N],head[N],id[N],dfn[N],top[N],sz[N],s[N],c[N];
struct data{
int to,next;
}E[N<<1];
int ls[N<<2],rs[N<<2],root[N];
deque<int> pat;
multiset<int> ch[N];
void addedge(int u,int v){
E[++tot].to=v,E[tot].next=head[u],head[u]=tot;
E[++tot].to=u,E[tot].next=head[v],head[v]=tot;
}
inline void dfsf(int u){
sz[u]=1;for(register int v,i=head[u];i;i=E[i].next)
if(v=E[i].to,v!=fa[u])fa[v]=u,dfsf(v),sz[u]+=sz[v];
}
inline void dfss(int u,int f){
dfn[id[u]=++dfs_cnt]=u;
top[u]=f,s[f]++;
register int mx=0,w;
for(register int v,i=head[u];i;i=E[i].next)
if(v=E[i].to,v!=fa[u])if(mx<sz[v])mx=sz[v],w=v;
if(mx)dfss(w,f);
for(register int v,i=head[u];i;i=E[i].next)
if(v=E[i].to,v!=fa[u]&&v!=w)dfss(v,v);
}
inline node merge(node& a,node& b,int l1,int l2,int l3){
node res;
res.l=min(a.l,l1+l2+b.l);
res.r=min(b.r,l2+l3+a.r);
return res;
}
inline void maintain(int rt,int x){
int d1=INF,d2=INF;
if(c[x])d1=d2=0;
if(ch[x].size())d1=min(d1,*ch[x].begin());
if(ch[x].size()>1)d2=min(d2,*(++ch[x].begin()));
seg[rt].l=seg[rt].r=d1;
}
inline void build(int rt,int l,int r){
if(l==r){
register int u=dfn[l];
for(register int v,i=head[u];i;i=E[i].next)
if(v=E[i].to,v!=fa[u]&&top[v]!=top[u])
build(root[v]=++cnt,id[v],id[v]+s[v]-1),
ch[u].insert(seg[root[v]].l+1);
maintain(rt,u);
}else{
build(ls[rt]=++cnt,l,mid);
build(rs[rt]=++cnt,mid+1,r);
seg[rt]=merge(seg[ls[rt]],seg[rs[rt]],mid-l,1,r-mid-1);
}
}
inline void find(int u){
pat.clear();
register int l=0;
while(u){
register int f=top[u];
pat.pf(l),pat.pf(u),pat.pf(f);
l+=id[u]-id[f]+1,u=fa[f];
}
}
inline void update(int rt,int l,int r,int i){
if(l==r){
register int u=dfn[l];
if(i+3<pat.size()){
register int nd=pat[i+2];
ch[u].erase(ch[u].find(seg[root[nd]].l+1));
update(root[nd],id[nd],id[nd]+s[nd]-1,i+3);
ch[u].insert(seg[root[nd]].l+1);
}
maintain(rt,u);
}else{
if(id[pat[i]]<=mid)update(ls[rt],l,mid,i);
else update(rs[rt],mid+1,r,i);
seg[rt]=merge(seg[ls[rt]],seg[rs[rt]],mid-l,1,r-mid-1);
}
}
inline int query(int rt,int l,int r,int i){
int res=INF;
if(l==r){
if(i+3<pat.size()){
register int nd=pat[i+2];
res=query(root[nd],id[nd],id[nd]+s[nd]-1,i+3);
}
res=min(res,seg[rt].l+pat[i+1]);
return res;
}else{
if(id[pat[i]]<=mid)res=min(query(ls[rt],l,mid,i),mid+1-id[pat[i]]+seg[rs[rt]].l+pat[i+1]);
else res=min(query(rs[rt],mid+1,r,i),seg[ls[rt]].r+id[pat[i]]-mid+pat[i+1]);
return res;
}
}
inline void read(int &res){
static char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int main(){
read(n);
for(register int a,b,i=1;i<n;i++)
read(a),read(b),addedge(a,b);
dfsf(1),dfss(1,1);read(Q);
build(root[1]=++cnt,1,s[1]);
while(Q--){
read(xx),read(yy),find(yy);
if(xx){
if(!cs){puts("-1");continue; }
printf("%d\n",query(1,1,s[1],1));
}else{
cs+=1-c[yy]*2,c[yy]=1-c[yy];
update(1,1,s[1],1);
}
}
return 0;
}

click it and link me

Launch CodeCogs Equation Editor